using KinonekoSoftware.CodariaDB.Documents.Templates;
namespace KinonekoSoftware.Studio.Pages.Theories
{
    public sealed class WVCTemplateDefinitionEditorViewModel : BooleanDialog
    {

        public static async Task<bool> Edit(WorldViewConfigViewModel owner, InstanceTemplate template)
        {
            var context = new DialogContext();

            context.Set(ContextBase.Key_Value, template);
            context.Set(ContextBase.Key_Parameter, owner);
            return await Question(new WVCTemplateDefinitionEditorViewModel(), context);
        }

        private InstanceTemplate         _template;
        private WorldViewConfigViewModel _wvc;
        private DataPartDefinition       _selected;

        public WVCTemplateDefinitionEditorViewModel()
        {
            EditDefinitionCommand      = CreateCommand(DoEditDefinitionCommand);
            EditPropertyCommand        = CreateCommand(DoEditPropertyCommand);
            ShiftUpDefinitionCommand   = CreateCommand<DataPartDefinition>(DoShiftUpDefinitionCommand);
            ShiftDownDefinitionCommand = CreateCommand<DataPartDefinition>(DoShiftDownDefinitionCommand);
            RemoveDefinitionCommand    = CreateCommand<DataPartDefinition>(DoRemoveDefinitionCommand);

        }

        protected override void OnReceive(DialogContext context)
        {
            if (context.Has(ContextBase.Key_Value) && context.Has(ContextBase.Key_Parameter))
            {
                _template = context.GetObject<InstanceTemplate>(ContextBase.Key_Value);
                _wvc      = context.GetObject<WorldViewConfigViewModel>(ContextBase.Key_Parameter);
                Selected  = _template.Definitions.FirstOrDefault();
            }

            base.OnReceive(context);
        }

        private async void DoEditDefinitionCommand()
        {
            //
            // 
            var set   = new HashSet<DataPartType>(_template.Definitions.Select(x => x.Type));
            var r     = await WVCTemplateDefinitionGeneratorViewModel.Select(set);
            var value = r.Value;
            
            if (!r.IsFinished)
            {
                return;
            }

            if (value is null || value.Count == 0)
            {
                return;
            }
            
            var mutex  = new HashSet<string>(
                                             _template.Definitions
                                                      .Select(x => x.Type)
                                                      .Select(x => DataPartTypeHelper.GetMutex.GetValueOrDefault(x))
                                                      .Where(x => !string.IsNullOrEmpty(x)));

            //
            // 不允许添加相同类型或者同属于一个互斥锁的Definition
            //
            var canAdd = value.Where(x => !set.Contains(x.Type) && !mutex.Contains(x.Mutex));

            foreach (var selector in canAdd)
            {
                if (_template.Definitions.Count > 15)
                {
                    break;
                }

                _template.Definitions.Add(new DataPartDefinition
                {
                    Type  = selector.Type,
                    Index = _template.Definitions.Count,
                });
            }
            
            
            _wvc.SetDirtyState(true);
        }
        
        private async void DoEditPropertyCommand()
        {
            var r = await WVCTemplatePropertyEditorViewModel.Edit(_template.Properties);
            
            
            if (!r)
            {
                return;
            }
            
            _wvc.SetDirtyState(true);
        }
        
        private void DoShiftUpDefinitionCommand(DataPartDefinition target)
        {
            if (target is null)
            {
                return;
            }
            
            Definitions.ShiftUp(target, (instance, _, newIndex) =>
            {
                instance.Index = newIndex;
            });
            
            _wvc.SetDirtyState(true);
        }
        
        private void DoShiftDownDefinitionCommand(DataPartDefinition target)
        {
            
            if (target is null)
            {
                return;
            }
            
            Definitions.ShiftDown(target, (instance, _, newIndex) =>
            {
                instance.Index = newIndex;
            });
            
            _wvc.SetDirtyState(true);
        }
        
        private async void DoRemoveDefinitionCommand(DataPartDefinition target)
        {
            
            if (target is null)
            {
                return;
            }

            if (!await RemoveItem())
            {
                return;
            }

            Definitions.Remove(target);

            for (var i = 0; i < Definitions.Count; i++)
            {
                var item = Definitions[i];
                item.Index = i;
            }
            
            _wvc.SetDirtyState(true);
        }


        /// <summary>
        /// 获取或设置 <see cref="Selected"/> 属性。
        /// </summary>
        public DataPartDefinition Selected
        {
            get => _selected;
            set => SetValue(ref _selected, value);
        }
        public ObservableCollection<DataPartDefinition> Definitions => _template.Definitions;

        public ICommandEX EditDefinitionCommand      { get; }
        public ICommandEX EditPropertyCommand        { get; }
        public ICommandEX ShiftUpDefinitionCommand   { get; }
        public ICommandEX ShiftDownDefinitionCommand { get; }
        public ICommandEX RemoveDefinitionCommand    { get; }

    }
}